//
//  ViewController.m
//  TestTcpUdp
//
//  Created by leeson zhong on 2021/7/5.
//

#import "ViewController.h"
#import "TcpServerUtil.h"
#import "TcpClientUtil.h"
#import "UdpServerUtil.h"
#import "UdpClientUtil.h"
#import "InputIpPortView.h"

#define DEF_HEX @"1234567890abcdefABCDEF"

@interface ViewController ()<UITextViewDelegate,InputIpPortViewDelegate,TcpServerUtilDelegate,TcpClientUtilDelegate,UdpServerUtilDelegate,UdpClientUtilUtilDelegate>{
    BOOL tcp_server_create;
    BOOL tcp_client_create;
    BOOL udp_server_create;
    BOOL udp_client_create;
    int show_page;
    
    NSString *tcpServerData;
    NSString *tcpClientData;
    NSString *udpServerData;
    NSString *udpClientData;
    
    TcpServerUtil *tcpServerUtil;
    TcpClientUtil *tcpClientUtil;
    UdpServerUtil *udpServerUtil;
    UdpClientUtil *udpClientUtil;
    
    InputIpPortView *inputIpPortView;
    UIView *inputIpPortBackgroundView;
}
@property (weak, nonatomic) IBOutlet UIButton *tcpServerButton;
@property (weak, nonatomic) IBOutlet UIButton *tcpClientButton;
@property (weak, nonatomic) IBOutlet UIButton *udpServerButton;
@property (weak, nonatomic) IBOutlet UIButton *udpClientButton;
@property (weak, nonatomic) IBOutlet UIButton *createButton;
@property (weak, nonatomic) IBOutlet UILabel *socketMessageLabel;
@property (weak, nonatomic) IBOutlet UITextView *receiveDataTextView;
@property (weak, nonatomic) IBOutlet UITextView *sendDataTextView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.receiveDataTextView.editable = false;
    self.sendDataTextView.delegate = self;
    tcp_server_create = NO;
    tcp_client_create = NO;
    udp_server_create = NO;
    udp_client_create = NO;
    show_page = 0;
    tcpServerData = @"";
    tcpClientData = @"";
    udpServerData = @"";
    udpClientData = @"";
}

//限制只能输入十六进制的数字和字符
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    //点击return退出键盘
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:DEF_HEX]invertedSet];
    NSString *filtered = [[text componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    BOOL basicTest = [text isEqualToString:filtered];
    if(!basicTest){
        return NO;
    }
    return YES;
}


- (IBAction)touchUpTcpServeerButton:(id)sender {
    if (show_page == 0){
        return;
    }
    show_page = 0;
    self.receiveDataTextView.text=tcpServerData;
    self.tcpServerButton.selected = YES;
    self.tcpClientButton.selected = NO;
    self.udpServerButton.selected = NO;
    self.udpClientButton.selected = NO;
    if (tcp_server_create){
        self.createButton.selected = YES;
        self.socketMessageLabel.text = [NSString stringWithFormat:@"create server port:%d",[tcpServerUtil getServerPort]];
    }else {
        self.createButton.selected = NO;
        self.socketMessageLabel.text = @"";
    }
}
- (IBAction)touchUpTcpClientButton:(id)sender {
    if (show_page == 1){
        return;
    }
    show_page = 1;
    self.receiveDataTextView.text=tcpClientData;
    self.tcpServerButton.selected = NO;
    self.tcpClientButton.selected = YES;
    self.udpServerButton.selected = NO;
    self.udpClientButton.selected = NO;
    if (tcp_client_create){
        self.createButton.selected = YES;
        self.socketMessageLabel.text = [NSString stringWithFormat:@"client connect ip:%@;port:%d",[tcpClientUtil getServerIp],[tcpClientUtil getServerPort]];
    }else {
        self.createButton.selected = NO;
        self.socketMessageLabel.text = @"";
    }
}
- (IBAction)touchUpUdpServerButton:(id)sender {
    if (show_page == 2){
        return;
    }
    show_page = 2;
    self.receiveDataTextView.text=udpServerData;
    self.tcpServerButton.selected = NO;
    self.tcpClientButton.selected = NO;
    self.udpServerButton.selected = YES;
    self.udpClientButton.selected = NO;
    if (udp_server_create){
        self.createButton.selected = YES;
        self.socketMessageLabel.text = [NSString stringWithFormat:@"create server port:%d",[udpServerUtil getServerPort]];
    }else {
        self.createButton.selected = NO;
        self.socketMessageLabel.text = @"";
    }
}
- (IBAction)touchUpUdpClient:(id)sender {
    if (show_page == 3){
        return;
    }
    show_page = 3;
    self.receiveDataTextView.text=udpClientData;
    self.tcpServerButton.selected = NO;
    self.tcpClientButton.selected = NO;
    self.udpServerButton.selected = NO;
    self.udpClientButton.selected = YES;
    if (udp_client_create){
        self.createButton.selected = YES;
        self.socketMessageLabel.text = [NSString stringWithFormat:@"client connect ip:%@;port:%d",[udpClientUtil getServerIp],[udpClientUtil getServerPort]];
    }else {
        self.createButton.selected = NO;
        self.socketMessageLabel.text = @"";
    }
}
- (IBAction)touchUpCreateButton:(id)sender {
    switch (show_page){
        case 0:{
            if (!tcp_server_create){
                [self showCreateDialog];
            }else {
                [tcpServerUtil close];
            }
        }break;
        case 1:{
            if (!tcp_client_create){
                [self showCreateDialog];
            }else {
                [tcpClientUtil close];
            }
        }break;
        case 2:{
            if (!udp_server_create){
                [self showCreateDialog];
            }else {
                [udpServerUtil close];
            }
        }break;
        case 3:{
            if (!udp_client_create){
                [self showCreateDialog];
            }else {
                [udpClientUtil close];
            }
        }break;
    }
}

-(void)showCreateDialog{
    if (inputIpPortView) {
        return;
    }
    inputIpPortBackgroundView = [[UIView alloc] initWithFrame:self.view.bounds];
    inputIpPortBackgroundView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:inputIpPortBackgroundView];
    [self.view bringSubviewToFront:inputIpPortBackgroundView];
    NSArray *objs = [[NSBundle mainBundle] loadNibNamed:@"InputIpPortView" owner:nil options:nil];
    inputIpPortView = objs.firstObject;
    inputIpPortView.frame = CGRectMake(0, inputIpPortBackgroundView.bounds.size.height/4, inputIpPortBackgroundView.bounds.size.width, inputIpPortBackgroundView.bounds.size.height/2);
    [inputIpPortBackgroundView addSubview:inputIpPortView];
    inputIpPortView.delegate = self;
    if (show_page==0 || show_page == 2) {
        inputIpPortView.showIP = NO;
    }else{
        inputIpPortView.showIP = YES;
    }
    
}

- (IBAction)touchUpClearButton:(id)sender {
    self.receiveDataTextView.text=@"";
    switch (show_page){
        case 0:{
            tcpServerData = @"";
        }break;
        case 1:{
            tcpClientData = @"";
        }break;
        case 2:{
            udpServerData = @"";
        }break;
        case 3:{
            udpClientData = @"";
        }break;
    }
}
- (IBAction)touchUpSendButton:(id)sender {
    NSString *text = self.sendDataTextView.text;
    if (!text) {
        return;
    }
    switch (show_page){
        case 0:{
            if (tcp_server_create) {
                [tcpServerUtil sendData:[self nsdataFromHexString:text]];
            }
        }break;
        case 1:{
            if (tcp_client_create) {
                
                [tcpClientUtil sendData:[self nsdataFromHexString:text]];
            }
        }break;
        case 2:{
            if (udp_server_create) {
                if ([udpServerUtil getClientIp]) {
                    [udpServerUtil sendData:[self nsdataFromHexString:text]];
                }
            }
        }break;
        case 3:{
            if (udp_client_create) {
                [udpClientUtil sendData:[self nsdataFromHexString:text]];
            }
        }break;
    }
}

-(NSString *)hexStringFromNSdata:(NSData *)data{
    Byte *byteData = (Byte *)[data bytes];
    NSString *hexString = @"";
    for (int i=0; i<data.length; i++) {
        hexString = [NSString stringWithFormat:@"%@%02X",hexString,byteData[i]];
    }
    return hexString;
}

-(NSData *)nsdataFromHexString:(NSString *)hexString{
    const char* ch = [[hexString lowercaseString] cStringUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* data = [NSMutableData data];

    while (*ch) {
        if (*ch == ' ') {
            continue;
        }
        char byte = 0;
        if ('0' <= *ch && *ch <= '9') {
            byte = *ch - '0';
        }

        else if ('a' <= *ch && *ch <= 'f') {
            byte = *ch - 'a' + 10;
        }

        else if ('A' <= *ch && *ch <= 'F') {
            byte = *ch - 'A' + 10;
        }
        ch++;
        byte = byte << 4;
        if (*ch) {
            if ('0' <= *ch && *ch <= '9') {
                byte += *ch - '0';
            } else if ('a' <= *ch && *ch <= 'f') {
                byte += *ch - 'a' + 10;
            }

            else if('A' <= *ch && *ch <= 'F')
            {
                byte += *ch - 'A' + 10;
            }
            ch++;
        }
        [data appendBytes:&byte length:1];
    }
    return data;
}

#pragma InputIpPortViewDelegate
- (void)onInputIpPortViewCancel{
    if (inputIpPortView) {
        [inputIpPortView removeFromSuperview];
        inputIpPortView = nil;
        [inputIpPortBackgroundView removeFromSuperview];
        inputIpPortBackgroundView = nil;
    }
}

- (void)onInputIpPortViewComfirmIp:(NSString *)ip Port:(NSString *)port{
    if (inputIpPortView) {
        [inputIpPortView removeFromSuperview];
        inputIpPortView = nil;
        [inputIpPortBackgroundView removeFromSuperview];
        inputIpPortBackgroundView = nil;
    }
    if (show_page == 1 || show_page == 3) {
        if ([InputIpPortView isIp:ip] == NO) {
            NSLog(@"Incorrect ip format");
            return;
        }
    }
    if ([InputIpPortView isPort:port] == NO) {
        NSLog(@"Incorrect port format");
        return;
        
    }
    switch (show_page){
        case 0:{
            tcp_server_create = true;
            self.createButton.selected = YES;
            self.socketMessageLabel.text = [NSString stringWithFormat:@"create server port:%@",port];
            tcpServerUtil = [[TcpServerUtil alloc] init];
            tcpServerUtil.delegate = self;
            [tcpServerUtil initWithServerPort:[port intValue]];
        }break;
        case 1:{
            tcp_client_create = true;
            self.createButton.selected = YES;
            self.socketMessageLabel.text = [NSString stringWithFormat:@"client connect ip:%@;port:%@",ip,port];
            tcpClientUtil = [[TcpClientUtil alloc] init];
            tcpClientUtil.delegate = self;
            [tcpClientUtil initWithServerIp:ip Port:[port intValue]];
        }break;
        case 2:{
            udp_server_create = true;
            self.createButton.selected = YES;
            self.socketMessageLabel.text = [NSString stringWithFormat:@"create server port:%@",port];
            udpServerUtil = [[UdpServerUtil alloc] init];
            udpServerUtil.delegate = self;
            [udpServerUtil initWithServerPort:[port intValue]];
        }break;
        case 3:{
            udp_client_create = true;
            self.createButton.selected = YES;
            self.socketMessageLabel.text = [NSString stringWithFormat:@"client connect ip:%@;port:%@",ip,port];
            udpClientUtil = [[UdpClientUtil alloc] init];
            udpClientUtil.delegate = self;
            [udpClientUtil initWithServerIp:ip Port:[port intValue]];
        }break;
    }
}

#pragma TcpServerUtilDelegate
-(void)onTcpServerAcceptClient:(BOOL)flag ClientIp:(NSString *)clientIp ClientPort:(int)clientPort{
    if (flag){
        tcpServerData = [NSString stringWithFormat:@"%@client[%@:%d] connected\n",tcpServerData,clientIp,clientPort];
    }else {
        tcpServerData = [NSString stringWithFormat:@"%@client[%@:%d] disconnected\n",tcpServerData,clientIp,clientPort];
    }
    if (show_page == 0) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->tcpServerData;
        });
    }
}
-(void)onTcpServerReceiveData:(NSData *)data ClientIp:(NSString *)clientIp ClientPort:(int)clientPort{
    tcpServerData = [NSString stringWithFormat:@"%@%@\n",tcpServerData,[self hexStringFromNSdata:data]];
    if (show_page == 0) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->tcpServerData;
        });
    }
}
-(void)onTcpServerClose{
    tcp_server_create = false;
    if (show_page == 0){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.createButton.selected = NO;
            self.socketMessageLabel.text = @"";
        });
    }
}

#pragma TcpClientUtilDelegate
-(void)onTcpClientConnectServer:(BOOL)flag{
    if (flag){
        tcpClientData =  [NSString stringWithFormat:@"%@connected\n",tcpClientData];
    }else {
        tcpClientData =  [NSString stringWithFormat:@"%@disconnected\n",tcpClientData];
    }
    if (show_page ==1) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->tcpClientData;
        });
    }
}
-(void)onTcpClientReceiveData:(NSData *)data ServerIp:(NSString *)serverIp ServerPort:(int)serverPort{
    tcpClientData = [NSString stringWithFormat:@"%@%@\n",tcpClientData,[self hexStringFromNSdata:data]];
    if (show_page == 1){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->tcpClientData;
        });
    }
}
-(void)onTcpClientClose{
    tcp_client_create = false;
    if (show_page == 1){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.createButton.selected = NO;
            self.socketMessageLabel.text = @"";
        });
    }
}

#pragma UdpServerUtilDelegate
-(void)onUdpServerReceiveNewConnectionIp:(NSString *)ip Port:(int)port{
    udpServerData = [NSString stringWithFormat:@"%@receive client:[%@:%d] data\n",udpServerData,ip,port];
}
-(void)onUdpServerReceiveData:(NSData *)data ClientIp:(NSString *)clientIp ClientPort:(int)clientPort{
    udpServerData = [NSString stringWithFormat:@"%@%@\n",udpServerData,[self hexStringFromNSdata:data]];
    if (show_page == 2){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->udpServerData;
        });
    }
}
-(void)onUdpServerClose{
    udp_server_create = false;
    if (show_page == 2){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.createButton.selected = NO;
            self.socketMessageLabel.text = @"";
        });
    }
}

#pragma UdpClientUtilUtilDelegate
-(void)onUdpClientReceiveNewConnectionIp:(NSString *)ip Port:(int)port{
    udpClientData = [NSString stringWithFormat:@"%@Data not from the sever was received once,from:[%@:%d]\n",udpClientData,ip,port];
}
-(void)onUdpClientReceiveData:(NSData *)data ServerIp:(NSString *)serverIp ServerPort:(int)serverPort{
    udpClientData = [NSString stringWithFormat:@"%@%@\n",udpClientData,[self hexStringFromNSdata:data]];
    if (show_page == 3){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.receiveDataTextView.text = self->udpClientData;
        });
    }
}
-(void)onUdpClientClose{
    udp_client_create = false;
    if (show_page == 3){
        dispatch_async(dispatch_get_main_queue(), ^{
            self.createButton.selected = NO;
            self.socketMessageLabel.text = @"";
        });
    }
}

@end
